﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;

namespace ProgettoWlanService
{
    public partial class WlanService : ServiceBase
    {
        public WlanService()
        {
            InitializeComponent();

            timer = new System.Timers.Timer();
            timer.Interval = 5000;
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);

            updatedNetworkList = new Dictionary<string, UInt32>();
            places = new List<Place>();
        }
        
        // VARIABILI PRIVATE
        private System.Timers.Timer timer;
        private LogFile networks;
        
        // The list of the nearest available networks
        private Dictionary<string, UInt32> updatedNetworkList;
        private List<Place> places;
        private string currentPlace;


        /* *** *** *** *** *** *** *** *** *** *** *** */

        protected override void OnStart(string[] args) {
            
            int count = 0;

            Dictionary<string, string> NICList = Wifi.getInterfaces();
            while(NICList.Count == 0 && count != 5) {
                NICList = Wifi.getInterfaces();
                System.Threading.Thread.Sleep(1000);
                count++;
            }         
            if(count == 5)
                OnStop(); // terminates service

            timer.Start();

            // WriteLog("Service started.");

        }

        private void check_Places() {

            // WriteLog("Checking places...");
            
            ReadCfgFile cfg = new ReadCfgFile("export.cfg");
            cfg.populate(ref places);
            
            // [WHERE AM I? function]
            
            // lista nome posto - conteggio di reti uguali alle updatedNetwork
	        Dictionary<string, UInt32> list = new Dictionary<string,UInt32>();

	        //contatore del numero di reti uguali (aggiornate) al posto iesimo
	        UInt32 count;

	        if (places.Count != 0) {
		
		        for (int i = 0; i < places.Count; i++) {

			        count = 0;
			        Dictionary<string, UInt32> iNetworkList = places[i].getNetworkList();
			        foreach (string sKey in updatedNetworkList.Keys) {
				        if (iNetworkList.ContainsKey(sKey)) {
					        count++;
				        }
			        }

			        list.Add(places[i].getPlaceName(), count);
		        } //fine for places
	
		        uint max = list.Max(kvp => kvp.Value);
		        string pName = list.Where(kvp => kvp.Value == max).Select(kvp => kvp.Key).First();

		        string msg;
		        float percent = (float)max / (float)updatedNetworkList.Count;

		        if (max != 0) {
			        msg = "You might be in: '" + pName + "' (" + (percent * 100) + "% accuracy) ";

                    if (currentPlace == pName)
                        return;
                    else
                        currentPlace = pName;

                    for (int i = 0; i < places.Count; i++) {
                        if (pName == places[i].getPlaceName()) {

                            foreach(string action in places[i].getActionList()) {
                                if(action == "Firewall") {
                                    string fileName = @"C:\Users\Alessandro Avila\Polito\Primo anno\Programmazione di sistema\C++\AutoIt executable files\firewall.exe";
                                    ApplicationLoader.PROCESS_INFORMATION procInfo;
                                    ApplicationLoader.StartProcessAndBypassUAC(fileName, out procInfo);
                                    
                                }
                                else if(action == "Networks") {
                                // nop (al momento)
                                }
                                else {
                                    string fileName = action;
                                    ApplicationLoader.PROCESS_INFORMATION procInfo;
                                    ApplicationLoader.StartProcessAndBypassUAC(fileName, out procInfo);
                                }
                            }

                        }
                    }
		        }
		        else {
                    // Magari lanciare un programma che dice proprio questo (Nuovo posto: registrarlo tramite l'app
                    // e assegnargli azioni
			        msg = "You are not in a registered place.";
		        }

	        }
	        else {
		        // MessageBox.Show("There are no registered places.", "Where am I?", MessageBoxButtons.OK);
	        }
            
        }

        protected override void OnStop() {
            networks.delete("networks.txt");
        }


        // Other methods

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {

            networks = new LogFile("networks.txt");

            updatedNetworkList = Wifi.getAvailableNetworkList();
            // WriteLog("Writing on file \"networks.txt\"...");

            foreach (string networkName in updatedNetworkList.Keys) {
                if(networkName == "") {
                    networks.write("Unknown" + ":" + updatedNetworkList[networkName]);
                    continue;
                }
                networks.write(networkName + ":" + updatedNetworkList[networkName]);
            }

            networks.close();

            check_Places();
        }

        // use or not?: I don't know yet
        static void WriteLog(string msg) {
            EventLog evt = new EventLog("WlanService");
            string message = msg + ": "
                + DateTime.Now.ToShortDateString() + " "
                + DateTime.Now.ToLongTimeString();
            evt.Source = "WlanService";
            evt.WriteEntry(message, EventLogEntryType.Information);
        }
    }
}